﻿using System.ComponentModel;
using AutoMapper;
using Furion.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using MySql.EntityFrameworkCore.Extensions;
using XinGuanERP.Db;
using XinGuanERP.Models.Po.business;
using XinGuanERP.Models.Vo.business;
using XinGuanERP.Services.business.IServices;
using XinGuanERP.Utils;

namespace XinGuanERP.Services.business
{
    public class ProductStockService : IProductStockService, ITransient
    {
        private readonly DefaultDbContext _defaultDbContext;
        public ProductStockService(DefaultDbContext defaultDbContext)
        {
            _defaultDbContext = defaultDbContext;
        }

        public bool InProductStock(ProductStockVo productStockVo)
        {
            // 是否第一次入库
            var res = _defaultDbContext.ProductStocks.FirstOrDefault(t => t.ProductId == productStockVo.ProductId);
            // 是的话添加
            if (res == null)
            {
                var productStockConfig = new MapperConfiguration(cfg =>
                {
                    cfg.CreateMap<ProductStockVo, ProductStock>()
                        .ForMember(dest => dest.Stock, opt => opt.Ignore())
                        .AfterMap((src, des) => des.Id = StrUtil.GUID())
                        .BeforeMap((src, des) => des.Stock = src.ProductInStock)
                        .BeforeMap((src, des) => des.CreateTime = DateTime.Now)
                        .BeforeMap((src, des) => des.CreateUserId = SecurityUtil.FindClaimValue("UserId"))
                        .BeforeMap((src, des) => des.CreateUserName = SecurityUtil.FindClaimValue("UserName"));
                });
                var productStockMapper = productStockConfig.CreateMapper();
                var productStock = productStockMapper.Map<ProductStock>(productStockVo);
                var inStockConfig = new MapperConfiguration(cfg =>
                {
                    cfg.CreateMap<ProductStockVo, InStock>()
                        .ForMember(dest => dest.Id, opt => opt.Ignore())
                        .BeforeMap((src, des) => des.Id = StrUtil.GUID())
                        .BeforeMap((src, des) => des.CreateTime = DateTime.Now)
                        .BeforeMap((src, des) => des.CreateUserId = SecurityUtil.FindClaimValue("UserId"))
                        .BeforeMap((src, des) => des.CreateUserName = SecurityUtil.FindClaimValue("UserName"));
                });
                var inStockMapper = inStockConfig.CreateMapper();
                var inStock = inStockMapper.Map<InStock>(productStockVo);
                _defaultDbContext.ProductStocks.Add(productStock);
                _defaultDbContext.InStocks.Add(inStock);
                return _defaultDbContext.SaveChanges() > 0;
            }
            // 不是的话更新
            else
            {
                var config = new MapperConfiguration(cfg =>
                {
                    cfg.CreateMap<ProductStockVo, ProductStock>()
                        .ForMember(dest => dest.Id, opt => opt.Ignore())
                        .ForMember(dest => dest.Stock, opt => opt.Ignore())
                        .BeforeMap((src, des) => des.UpdateTime = DateTime.Now)
                        .BeforeMap((src, des) => des.UpdateUserId = SecurityUtil.FindClaimValue("UserId"))
                        .BeforeMap((src, des) => des.UpdateUserName = SecurityUtil.FindClaimValue("UserName"))
                        .BeforeMap((src, des) => des.Stock = res.Stock + src.ProductInStock);
                });
                var mapper = config.CreateMapper();
                mapper.Map(productStockVo, res);
                _defaultDbContext.ProductStocks.Update(res);
                var inStockConfig = new MapperConfiguration(cfg =>
                {
                    cfg.CreateMap<ProductStockVo, InStock>()
                        .ForMember(dest => dest.Id, opt => opt.Ignore())
                        .BeforeMap((src, des) => des.Id = StrUtil.GUID())
                        .BeforeMap((src, des) => des.CreateTime = DateTime.Now)
                        .BeforeMap((src, des) => des.CreateUserId = SecurityUtil.FindClaimValue("UserId"))
                        .BeforeMap((src, des) => des.CreateUserName = SecurityUtil.FindClaimValue("UserName"));
                });
                var inStockMapper = inStockConfig.CreateMapper();
                var inStock = inStockMapper.Map<InStock>(productStockVo);
                _defaultDbContext.InStocks.Add(inStock);
                return _defaultDbContext.SaveChanges() > 0;
            }
            
        }

        public bool OutProductStock(ProductStockVo productStockVo)
        {
            // 出库
            // 检查库存是否存在
            // 不存在返回false
            // 出库数量 > 库存数量 false
            // 出库数量 <= 库存数量 true
            // 出库数量 = 库存数量 删除库存
            var res = _defaultDbContext.ProductStocks.FirstOrDefault(t => t.ProductId == productStockVo.ProductId);
            if (res == null) return false;
            var stock = res.Stock;
            if (productStockVo.ProductOutStock > stock) return false;
            else if (productStockVo.ProductOutStock < stock)
            {
                var config = new MapperConfiguration(cfg =>
                {
                    cfg.CreateMap<ProductStockVo, ProductStock>()
                        .ForMember(dest => dest.Id, opt => opt.Ignore())
                        .ForMember(dest => dest.Stock, opt => opt.Ignore())
                        .BeforeMap((src, des) => des.UpdateTime = DateTime.Now)
                        .BeforeMap((src, des) => des.UpdateUserId = SecurityUtil.FindClaimValue("UserId"))
                        .BeforeMap((src, des) => des.UpdateUserName = SecurityUtil.FindClaimValue("UserName"))
                        .BeforeMap((src, des) => des.Stock = stock - src.ProductOutStock);
                });
                var mapper = config.CreateMapper();
                mapper.Map(productStockVo, res);
                _defaultDbContext.ProductStocks.Update(res);
                var outStockConfig = new MapperConfiguration(cfg =>
                {
                    cfg.CreateMap<ProductStockVo, OutStock>()
                        .ForMember(dest => dest.Id, opt => opt.Ignore())
                        .BeforeMap((src, des) => des.Id = StrUtil.GUID())
                        .BeforeMap((src, des) => des.CreateTime = DateTime.Now)
                        .BeforeMap((src, des) => des.CreateUserId = SecurityUtil.FindClaimValue("UserId"))
                        .BeforeMap((src, des) => des.CreateUserName = SecurityUtil.FindClaimValue("UserName"));
                });
                var outStockMapper = outStockConfig.CreateMapper();
                var outStock = outStockMapper.Map<OutStock>(productStockVo);
                _defaultDbContext.OutStocks.Add(outStock);
                return _defaultDbContext.SaveChanges() > 0;
            }
            else
            {
                _defaultDbContext.ProductStocks.Remove(res);
                var outStockConfig = new MapperConfiguration(cfg =>
                {
                    cfg.CreateMap<ProductStockVo, OutStock>()
                        .ForMember(dest => dest.Id, opt => opt.Ignore())
                        .BeforeMap((src, des) => des.Id = StrUtil.GUID())
                        .BeforeMap((src, des) => des.CreateTime = DateTime.Now)
                        .BeforeMap((src, des) => des.CreateUserId = SecurityUtil.FindClaimValue("UserId"))
                        .BeforeMap((src, des) => des.CreateUserName = SecurityUtil.FindClaimValue("UserName"));
                });
                var outStockMapper = outStockConfig.CreateMapper();
                var outStock = outStockMapper.Map<OutStock>(productStockVo);
                _defaultDbContext.OutStocks.Add(outStock);
                return _defaultDbContext.SaveChanges() > 0;
            }
            
        }

        // public bool DeleteProductStock(string id)
        // {
        //     var res = _defaultDbContext.ProductStocks.FirstOrDefault(t => t.Id == id);
        //     if (res == null) return false;
        //     _defaultDbContext.ProductStocks.Remove(res);
        //     return _defaultDbContext.SaveChanges() > 0;
        // }

        public PageResult<ProductStockVo> GetProductStockWithPage(int page, int pageSize, ProductStockVo productStockVo)
        {
            var res = new List<ProductStockVo>();
            var count = 0;
            var sql = from ps in _defaultDbContext.ProductStocks
                                    join p in _defaultDbContext.Products
                                        on ps.ProductId equals p.Id
                                    select new ProductStockVo
                       {
                           Id = ps.Id,
                           ProductId = p.Id,
                           Name = p.Name,
                           Model = p.Model,
                           Unit = p.Unit,
                           Remark = ps.Remark,
                           ImageUrl = p.ImageUrl,
                           Stock = ps.Stock,
                       };
            if (!string.IsNullOrWhiteSpace(productStockVo.Name))
            {
                res = sql.Where(t => 
                        EF.Functions.Like(t.Name, "%" + productStockVo.Name + "%"))
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t => 
                    EF.Functions.Like(t.Name, "%" + productStockVo.Name + "%"));
            }
            else if (!string.IsNullOrWhiteSpace(productStockVo.Model))
            {
                res = sql.Where(t =>
                        EF.Functions.Like(t.Model, "%" + productStockVo.Model + "%"))
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t =>
                    EF.Functions.Like(t.Model, "%" + productStockVo.Model + "%"));
            }
            else if (!string.IsNullOrWhiteSpace(productStockVo.Name) && !string.IsNullOrWhiteSpace(productStockVo.Model))
            {
                res = sql.Where(t =>
                        EF.Functions.Like(t.Name, "%" + productStockVo.Name + "%"))
                    .Where(t => 
                        EF.Functions.Like(t.Model, "%" + productStockVo.Model + "%"))
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql
                    .Where(t =>
                        EF.Functions.Like(t.Name, "%" + productStockVo.Name + "%"))
                    .Count(t => EF.Functions.Like(t.Model, "%" + productStockVo.Model + "%"));
            }
            else if (!string.IsNullOrWhiteSpace(productStockVo.ThreeCategoryId))
            {
                res = sql.Where(t => t.ThreeCategoryId == productStockVo.ThreeCategoryId)
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t => t.ThreeCategoryId == productStockVo.ThreeCategoryId);
            }
            else if (!string.IsNullOrWhiteSpace(productStockVo.TwoCategoryId))
            {
                res = sql.Where(t => t.TwoCategoryId == productStockVo.TwoCategoryId)
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t => t.TwoCategoryId == productStockVo.TwoCategoryId);
            }
            else if (!string.IsNullOrWhiteSpace(productStockVo.OneCategoryId))
            {
                res = sql.Where(t => t.OneCategoryId == productStockVo.OneCategoryId)
                    .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count(t => t.OneCategoryId == productStockVo.OneCategoryId);
            }
            else
            {
                res = sql.Skip((page - 1) * pageSize).Take(pageSize).ToList();
                count = sql.Count();
            }

            return new PageResult<ProductStockVo>()
            {
                Items = new List<ProductStockVo>(res),
                Total = count
            };
        }

        public List<ProductStockVo> GetProductStockList()
        {
            var res = new List<ProductStockVo>();
            var sql = from ps in _defaultDbContext.ProductStocks
                join p in _defaultDbContext.Products
                    on ps.ProductId equals p.Id
                select new ProductStockVo
                {
                    Id = ps.Id,
                    ProductId = p.Id,
                    Name = p.Name,
                    Model = p.Model,
                    Unit = p.Unit,
                    Remark = ps.Remark,
                    ImageUrl = p.ImageUrl,
                    Stock = ps.Stock
                };
            res = sql.ToList();
            return res;
        }
    }
}
